package pkg.networking;

import java.awt.Point;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import pkg.commands.SysCmd;

public class BombServer extends ServerBase {
	
	private final int SERVERID = -1;
	protected ArrayList<ClientInfo> clients;
	protected boolean started = false;
	
	public BombServer()
	{
		clients = new ArrayList<ClientInfo>();
	}
	
	protected void clientConnected(SocketChannel socket)
	{
		ClientInfo info = new ClientInfo(socket,0);
		
		int id = firstEmptyClientIndex();
		
		if(id == -1)
		{
			id = clients.size();
			info.id = id;
			clients.add(info);
		}
		else
			clients.set(id, info);
	
		RemoteCommand cmd = new RemoteCommand(null,id);
		
		cmd.setFlags(RemoteCommand.Flags.Verrify);
		ByteBuffer buffer = ByteBuffer.wrap(this.serializeCommand(cmd).toByteArray());
		writeBytes(socket,buffer);
		
		log.info("Server is Verrifying Client with " + id + " ... ");
	}
	
	public void stop()
	{
		for(SelectionKey key : selector.keys())
			disconectKey(key);
		this.connected = false;
		log.info("Server Has ShutDown");
	}
	
	protected boolean onCommandReceived(RemoteCommand cmd)
	{
		if((cmd.getFlags() & RemoteCommand.Flags.Verrify) == RemoteCommand.Flags.Verrify)
		{
			compleateClientJoin(cmd);
			return false;
		}
		return true;
	}
	
	private void compleateClientJoin(RemoteCommand cmd)
	{
		ClientInfo newClient = getClient(cmd.getUserId());
		if(cmd.getObject() instanceof String)
		   newClient.name = (String)cmd.getObject();
		else
		{
		   this.disconectKey(newClient.getKey());
		   return;
		}
		
		RemoteCommand remote = new RemoteCommand(SysCmd.playerJoin(newClient.name, newClient.id, new Point()),SERVERID);
		remote.setFlags(RemoteCommand.Flags.PlayerJoin);
		log.info("Player " + newClient.name + " has Joined the game"); 
		
		for(ClientInfo client : clients)
		{
			

			if(client != newClient)
			{
			   send(remote, client);
			   RemoteCommand newRemote = new RemoteCommand(SysCmd.playerJoin(client.name, client.id, new Point()),SERVERID);
			   newRemote.setFlags(RemoteCommand.Flags.PlayerJoin);
			   this.send(newRemote, newClient); //notify new player of all players that are already hear
			}	
			
			RemoteCommand cmdFlags = new RemoteCommand(null,SERVERID); //this command is just flags
			cmdFlags.setFlags(RemoteCommand.Flags.SynchPositions);
			send(cmdFlags,client); 
		
		}
		
	
		//this.broadcastCommand(cmd);
	}
	
	private int firstEmptyClientIndex()
	{
		for(int i = 0; i < clients.size(); i++)
			if(clients.get(i) == null)
				return i;
		return -1;
	}
	
	private ClientInfo getClient(int id)
	{
		if(id < clients.size() && id >= 0)
			return clients.get(id);
		return null;
	}
	
	public void send(RemoteCommand cmd,ClientInfo info)
	{
		ByteBuffer buffer = ByteBuffer.wrap(serializeCommand(cmd).toByteArray());
		this.writeBytes(info.getKey(),buffer);
	}
	

	protected class ClientInfo
 	{
 		public int id;
 		public String name;
 		public SocketChannel channel;
 		
 		public ClientInfo(SocketChannel chan,int id)
 		{
 			channel = chan;
 			this.id = id;
 		}
 		
 		public SelectionKey getKey()
 		{
 			return channel.keyFor(selector);
 		}
 	}

}
